import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { HttpExceptionFilter } from './shared/http-exception.filter';
import { LoggingInterceptor } from './shared/logging.interceptor';
import redoc from 'redoc-express';

async function bootstrap() {
  const app = await NestFactory.create(AppModule); // 创建 NestJS 应用实例，使用 AppModule 作为根模块

  app.setGlobalPrefix('api'); // 设置全局路由前缀为 'api'，所有路由都将以 '/api' 开头

  app.useGlobalPipes( // 全局管道，用于验证和转换请求体
    new ValidationPipe({ // 验证管道，用于验证请求体参数
      whitelist: true, // 只允许在 DTO 中定义的属性，忽略其他属性
      forbidNonWhitelisted: true, // 拒绝包含非白名单属性的请求体
      transform: true, // 自动将请求体转换为 DTO 实例
    }),
  );

  app.useGlobalFilters(new HttpExceptionFilter()); // 全局异常过滤器，用于处理应用抛出的异常
  app.useGlobalInterceptors(new LoggingInterceptor()); // 全局拦截器，用于记录请求和响应日志 

  const config = new DocumentBuilder()
    .setTitle('NestJS Demo API')
    .setDescription('A practical demo to master NestJS')
    .setVersion('1.0')
    .addBearerAuth()
    .build(); // 创建 Swagger 文档配置，包含标题、描述、版本和 Bearer 认证
  const document = SwaggerModule.createDocument(app, config); // 创建 Swagger 文档，包含应用的路由和控制器信息
  SwaggerModule.setup('docs', app, document); // 设置 Swagger 文档的路由为 '/docs'，并将文档挂载到应用实例上

  // OpenAPI JSON for external UI
  const httpAdapter = app.getHttpAdapter();
  httpAdapter.get('/docs-json', (req, res) => res.json(document)); // 定义路由 '/docs-json'，返回 Swagger 文档的 JSON 格式

  // Redoc UI (替代 Scalar)
  app.use(
    '/redoc',
    redoc({
      title: 'API Reference', // Redoc 文档标题
      specUrl: '/docs-json', // Redoc 文档 JSON 格式的路由
      redocOptions: { noGoogleFonts: true }, // Redoc 选项，禁用 Google 字体
    }),
  );

  const port = process.env.PORT || 3000; // 从环境变量中获取端口号，默认使用 3000
  await app.listen(port as number); // 应用实例监听指定端口，等待请求到达
  console.log(`Server running on http://localhost:${port}`); // 打印应用运行信息，包括端口号
  console.log(`Swagger docs available at http://localhost:${port}/docs`); // 打印 Swagger 文档的访问地址
  console.log(`OpenAPI JSON available at http://localhost:${port}/docs-json`); // 打印 OpenAPI JSON 格式的文档访问地址
  console.log(`Redoc available at http://localhost:${port}/redoc`); // 打印 Redoc 文档的访问地址
}

bootstrap(); // 启动应用